package com.fastjars.shiro.chain;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.config.Ini;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.InitializingBean;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * FilterChainManager
 * 动态过滤链控制类
 * add-ons安装的时候处理动态过滤链
 *
 * @author Brant Liu <br> 邮箱：<br>lbf1988@qq.com <br>日期：<br>2018/08/23
 * @version 1.0.0
 */
public class FilterChainManager implements InitializingBean {
    private static final Log logger = LogFactory.getLog(FilterChainManager.class);

    private Map<String, String> filterChains = new LinkedHashMap();

    private ShiroFilterFactoryBean shiroFilterFactoryBean;

    public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
        return shiroFilterFactoryBean;
    }

    public void setShiroFilterFactoryBean(ShiroFilterFactoryBean shiroFilterFactoryBean) {
        this.shiroFilterFactoryBean = shiroFilterFactoryBean;
    }

    /**
     * 获取Shiro默认过滤管理器
     *
     * @return
     * @throws Exception
     */
    public DefaultFilterChainManager getDefaultFilterChainManager() throws Exception {
        AbstractShiroFilter shiroFilter = (AbstractShiroFilter) getShiroFilterFactoryBean().getObject();

        PathMatchingFilterChainResolver resolver = (PathMatchingFilterChainResolver) shiroFilter.getFilterChainResolver();
        // 过滤管理器
        return (DefaultFilterChainManager) resolver.getFilterChainManager();
    }

    /**
     * 清除过滤链配置
     *
     * @throws Exception
     */
    protected void clearFilterChains() throws Exception {
        getDefaultFilterChainManager().getFilterChains().clear();
    }

    /**
     * 添加过滤链
     *
     * @param definitions
     * @throws Exception
     */
    public void addFilter(String definitions) throws Exception {
        Ini ini = new Ini();
        ini.load(definitions);
        Ini.Section section = ini.getSection("urls");
        if (CollectionUtils.isEmpty(section)) {
            section = ini.getSection("");
        }
        this.addFilter(section);
    }

    /**
     * 添加过滤链
     *
     * @param filters
     * @throws Exception
     */
    public void addFilter(Map<String, String> filters) throws Exception {
        if (!filters.isEmpty()) {
            //重置当前过滤链
            initializingFilterChains();

            this.filterChains.putAll(filters);

            //清除过滤链配置
            this.clearFilterChains();
            this.getShiroFilterFactoryBean().getFilterChainDefinitionMap().clear();

            //重新设置过滤链
            this.getShiroFilterFactoryBean().setFilterChainDefinitionMap(filterChains);

            if (!CollectionUtils.isEmpty(filterChains)) {
                filterChains.forEach((url, definitionChains) -> {
                    try {
                        getDefaultFilterChainManager().createChain(url, definitionChains.trim().replace(" ", ""));
                    } catch (Exception e) {
                    }
                });
            }
        }
    }

    /**
     * 初始化过滤链
     */
    private void initializingFilterChains() {
        if (null == this.getShiroFilterFactoryBean()) {
            logger.debug("FilterChainManager属性shiroFilterFactoryBean未初始化");
        } else {
            this.filterChains.clear();
            this.filterChains.putAll(this.getShiroFilterFactoryBean().getFilterChainDefinitionMap());
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        initializingFilterChains();
    }
}
